/*
 * @Author: 0x9DEFA478
 * @Date: 2021-07-19 19:55:02
 * @LastEditTime: 2021-09-08 14:17:57
 * @LastEditors: 0x9DEFA478
 * @Description: 
 * QQ:2652450237
 * ============================================================================================================================================
 * 
 * 
 * 
 *                                                                                               ************      ****************************
 *                                                                                             ************      ****************************  
 *                                                                                           ************      ****************************    
 *                                                                                         ************      ****************************      
 *                                                                                       ************      ************                        
 *                                                                                     ************      ************                          
 *                                                                                   ************      ************                            
 *                                                                                 ************      ************                              
 *                                                                               ************      ************                                
 *                                                                             ************      ************                                  
 *                                                                           ************      ************                                    
 *                                                                         ************      ************                                      
 *                                                                       ************      ************                                        
 *                                                                     ************      ************                                          
 *                                                                   ************      ************                                            
 *                                                                 ************      ************                                              
 *                                                               ************      ************                                                
 *                                                             ************      ************                                                  
 *                                                           ************      ************                                                    
 *                                                         ************      ************                                                      
 *                                                       ************      ************                                                        
 *                                                     ************      ************                                                          
 *                                                   ************      ************                                                            
 *                                                 ************      ************                                                              
 *                                               ************      ************                                                                
 *                                             ************      ************                                                                  
 *                                           ************      ************                                                                    
 *                                         ************      ************                                                                      
 *                                       ************      ************                                                                        
 *                                     ************      ************                                                                          
 *                                   ************      ************                                                                            
 *                                 ************      ************                                                                              
 *                               ************      ************                                                                                
 *                             ************      ************                                                                                  
 *                           ************      ************                                                                                    
 *                         ************      ************                                                                                      
 *       ****************************      ************                                                                                        
 *     ****************************      ************                                                                                          
 *   ****************************      ************                                                                                            
 * ****************************      ************                                                                                              
 * 
 * 
 * 
 * ============================================================================================================================================
 * 
 */
#include "H_Font.h"
#include "H_String.h"

static void* GetBitmap_Ascii(H_Font* _this,H_Font** outFont,unsigned short unicode,int* Width);
static void* GetBitmap_Lib(H_Font* _this,H_Font** outFont,unsigned short unicode,int* Width);
static void* GetBitmap_LLib(H_Font* _this,H_Font** outFont,unsigned short unicode,int* Width);
static int GetFontWidth_Ascii(struct _H_Font* Font,unsigned short unicode);
static int GetFontWidth_Lib(struct _H_Font* Font,unsigned short unicode);
static int GetFontWidth_LLib(struct _H_Font* Font,unsigned short unicode);

static int FontDecode_Ascii(H_Font* Font);
static int FontDecode_Lib(H_Font* Font);
static int FontDecode_LLib(H_Font* Font);




/**
 * @brief 对一个空的Font进行初始化
 * @param Font
 * @param FontAddr
 * @return 0:成功 其他:失败
 */
int H_Font_Init(H_Font* Font,void* FontAddr,int Type){
  int Vertical_Num;
  int Horizontal_Num;

  Font->FontAddr=FontAddr;

  switch (Type)
  {
    case vH_Font_Type_Ascii:
      if(FontDecode_Ascii(Font)!=0){
        return -2;
      }
      Font->GetBitmap=GetBitmap_Ascii;
      Font->GetFontWidth=GetFontWidth_Ascii;
      break;

    case vH_Font_Type_Lib:
      if(FontDecode_Lib(Font)!=0){
        return -3;
      }
      Font->GetBitmap=GetBitmap_Lib;
      Font->GetFontWidth=GetFontWidth_Lib;
      break;

    case vH_Font_Type_LLib:
      if(FontDecode_LLib(Font)!=0){
        return -4;
      }
      Font->GetBitmap=GetBitmap_LLib;
      Font->GetFontWidth=GetFontWidth_LLib;
      break;
    
    default:
      return -1;
  }

  


  if(Font->IsHorizontal) {
    Horizontal_Num=Font->NumOfHorizontalBytes;
    Vertical_Num=Font->FontHeight;
  }
  else
  {
    Horizontal_Num=Font->NumOfHorizontalBytes;
    Vertical_Num=(Font->FontHeight+(8/Font->NumOfBitForPerPix-1))/(8/Font->NumOfBitForPerPix);
  }

  Font->CharBitmapSize=1+Horizontal_Num*Vertical_Num;

  Font->AsciiFont=NULL;
	
	return 0;
}

/**
 * @brief 获取一个字符串所需要的高度与宽度
 * @param Font 字体
 * @param UTF8String 字符串
 * @param Width 用于返回宽度
 * @param Height 用于返回高度
 * @return 0:获取成功 其他:获取失败
 */
int H_Font_GetStringSize(H_Font* Font,char* UTF8String,int* Width,int* Height){
  int res;
  unsigned short unicode;
  int Line;
  int fontwidth;

  int width;
  int mwidth;
  
  width=0;
  mwidth=0;


  Line=1;
  for(;;){
    res=H_UTF8_Decode(&UTF8String,&unicode);
    if(res!=0){
      return res-1;
    }
    if(unicode==0){
      if(width>mwidth){
        mwidth=width;
      }
      break;
    }

    if(unicode=='\r'){
      if(UTF8String[0]=='\n'){
        UTF8String=&UTF8String[0];
      }

      Line++;
      if(width>mwidth){
        mwidth=width;
      }
      width=0;
      continue;
    }

    if(unicode=='\n'){
      Line++;
      if(width>mwidth){
        mwidth=width;
      }
      width=0;
      continue;
    }


    fontwidth=Font->GetFontWidth(Font,unicode);
    if(fontwidth<0){
      return -1;
    }

    width+=fontwidth;

  }
    

  Width[0]=mwidth;
  Height[0]=Line*Font->FontHeight;
  return 0;
}




static void* GetBitmap_Ascii(H_Font* _this,H_Font** outFont,unsigned short unicode,int* Width){
  unsigned char* lib;

  if(unicode>127){
    return NULL;
  }

  lib=_this->FontAddr;

  lib=&lib[4+unicode*_this->CharBitmapSize];

  outFont[0]=_this;
  *Width=lib[0];
  return &lib[1];
}

static void* GetBitmap_Lib(H_Font* _this,H_Font** outFont,unsigned short unicode,int* Width){
  unsigned char* lib;

  if((unicode<128)&&(_this->AsciiFont!=NULL)){

    return _this->AsciiFont->GetBitmap(_this->AsciiFont,outFont,unicode,Width);
  }

  lib=_this->FontAddr;

  lib=&lib[4+unicode*_this->CharBitmapSize];

  outFont[0]=_this;
  *Width=lib[0];
  return &lib[1];
}

static void* GetBitmap_LLib(H_Font* _this,H_Font** outFont,unsigned short unicode,int* Width){
  unsigned char* lib;
  int tId;
  int eId;
  int Id;
  int CharNum;
  unsigned short tuni;
  unsigned short euni;
  unsigned short uni;

  if((unicode<128)&&(_this->AsciiFont!=NULL)){

    return _this->AsciiFont->GetBitmap(_this->AsciiFont,outFont,unicode,Width);
  }

  lib=_this->FontAddr;
  lib=&lib[8];

  CharNum=_this->CharNum;
  tId=0;
  eId=2*(_this->CharNum-1);
  while(eId>tId){

#if vH_Font_isBigend!=0
    ((unsigned char*)&tuni)[0]=lib[tId+1];
    ((unsigned char*)&tuni)[1]=lib[tId];
    ((unsigned char*)&euni)[0]=lib[eId+1];
    ((unsigned char*)&euni)[1]=lib[eId];
#else
    ((unsigned char*)&tuni)[0]=lib[tId];
    ((unsigned char*)&tuni)[1]=lib[tId+1];
    ((unsigned char*)&euni)[0]=lib[eId];
    ((unsigned char*)&euni)[1]=lib[eId+1];
#endif

    if(euni==unicode)
    {
      lib=&lib[CharNum*2+(eId/2)*_this->CharBitmapSize];

      outFont[0]=_this;
      *Width=lib[0];
      return &lib[1];
    }

    if(tuni==unicode)
    {
      lib=&lib[CharNum*2+(tId/2)*_this->CharBitmapSize];

      outFont[0]=_this;
      *Width=lib[0];
      return &lib[1];
    }

    Id=(((tId/2)+(eId/2))/2)*2;

#if vH_Font_isBigend!=0
    ((unsigned char*)&uni)[0]=lib[Id+1];
    ((unsigned char*)&uni)[1]=lib[Id];
#else
    ((unsigned char*)&uni)[0]=lib[Id];
    ((unsigned char*)&uni)[1]=lib[Id+1];
#endif

    if(uni>unicode){
      if((Id==tId)||(Id==eId)){
        return NULL;
      }
      eId=Id;
    }else if(uni==unicode)
    {
      lib=&lib[CharNum*2+(Id/2)*_this->CharBitmapSize];

      outFont[0]=_this;
      *Width=lib[0];
      return &lib[1];
    }else{
      if((Id==tId)||(Id==eId)){
        return NULL;
      }
      tId=Id;
    }

  }

  return NULL;
}

static int GetFontWidth_Ascii(struct _H_Font* Font,unsigned short unicode){
  unsigned char* lib;

  if(unicode>127){
    return -1;
  }

  lib=Font->FontAddr;

  lib=&lib[4+unicode*Font->CharBitmapSize];
  
  return (int)lib[0];
}

static int GetFontWidth_Lib(struct _H_Font* Font,unsigned short unicode){
  unsigned char* lib;

  if((unicode<128)&&(Font->AsciiFont!=NULL)){

    return Font->AsciiFont->GetFontWidth(Font->AsciiFont,unicode);
  }

  lib=Font->FontAddr;

  lib=&lib[4+unicode*Font->CharBitmapSize];
  
  return (int)lib[0];
}

static int GetFontWidth_LLib(struct _H_Font* Font,unsigned short unicode){

  unsigned char* lib;
  int tId;
  int eId;
  int Id;
  int CharNum;
  unsigned short tuni;
  unsigned short euni;
  unsigned short uni;

  if((unicode<128)&&(Font->AsciiFont!=NULL)){

    return Font->AsciiFont->GetFontWidth(Font->AsciiFont,unicode);
  }

  lib=Font->FontAddr;
  lib=&lib[8];

  CharNum=Font->CharNum;
  tId=0;
  eId=2*(Font->CharNum-1);
  while(eId>tId){

#if vH_Font_isBigend!=0
    ((unsigned char*)&tuni)[0]=lib[tId+1];
    ((unsigned char*)&tuni)[1]=lib[tId];
    ((unsigned char*)&euni)[0]=lib[eId+1];
    ((unsigned char*)&euni)[1]=lib[eId];
#else
    ((unsigned char*)&tuni)[0]=lib[tId];
    ((unsigned char*)&tuni)[1]=lib[tId+1];
    ((unsigned char*)&euni)[0]=lib[eId];
    ((unsigned char*)&euni)[1]=lib[eId+1];
#endif

    if(euni==unicode)
    {
      lib=&lib[CharNum*2+(eId/2)*Font->CharBitmapSize];

      return (int)lib[0];
    }

    if(tuni==unicode)
    {
      lib=&lib[CharNum*2+(tId/2)*Font->CharBitmapSize];

      return (int)lib[0];
    }

    Id=(((tId/2)+(eId/2))/2)*2;

#if vH_Font_isBigend!=0
    ((unsigned char*)&uni)[0]=lib[Id+1];
    ((unsigned char*)&uni)[1]=lib[Id];
#else
    ((unsigned char*)&uni)[0]=lib[Id];
    ((unsigned char*)&uni)[1]=lib[Id+1];
#endif

    if(uni>unicode){
      if((Id==tId)||(Id==eId)){
        return -1;
      }
      eId=Id;
    }else if(uni==unicode)
    {
      lib=&lib[CharNum*2+(Id/2)*Font->CharBitmapSize];

      return (int)lib[0];
    }else{
      if((Id==tId)||(Id==eId)){
        return -1;
      }
      tId=Id;
    }

  }

  return -1;
}







static int FontDecode_Ascii(H_Font* Font){
  unsigned char *lib;

  lib=Font->FontAddr;

  Font->FontHeight=lib[0];
  Font->FontMaxWidth=lib[1];
  Font->NumOfHorizontalBytes=lib[2];
  
  if(lib[3]&0x80){
    Font->IsHorizontal=0;
  }else{
    Font->IsHorizontal=-1;
  }

  if(lib[3]&0x40){
    Font->IsBigend=-1;
  }else{
    Font->IsBigend=0;
  }
  
  Font->NumOfBitForPerPix=lib[3]&0x3F;

  if((Font->NumOfBitForPerPix!=1)&&(Font->NumOfBitForPerPix!=2)&&(Font->NumOfBitForPerPix!=4)&&(Font->NumOfBitForPerPix!=8)){

    return -1;
  }


  return 0;
}

static int FontDecode_Lib(H_Font* Font){
  unsigned char *lib;

  lib=Font->FontAddr;

  Font->FontHeight=lib[0];
  Font->FontMaxWidth=lib[1];
  Font->NumOfHorizontalBytes=lib[2];
  
  if(lib[3]&0x80){
    Font->IsHorizontal=0;
  }else{
    Font->IsHorizontal=-1;
  }

  if(lib[3]&0x40){
    Font->IsBigend=-1;
  }else{
    Font->IsBigend=0;
  }
  
  Font->NumOfBitForPerPix=lib[3]&0x3F;

  if((Font->NumOfBitForPerPix!=1)&&(Font->NumOfBitForPerPix!=2)&&(Font->NumOfBitForPerPix!=4)&&(Font->NumOfBitForPerPix!=8)){

    return -1;
  }

  return 0;
}

static int FontDecode_LLib(H_Font* Font){
  unsigned char *lib;
  int CharNum;

  lib=Font->FontAddr;


#if vH_Font_isBigend!=0
  ((unsigned char*)(&CharNum))[0]=lib[3];
  ((unsigned char*)(&CharNum))[1]=lib[2];
  ((unsigned char*)(&CharNum))[2]=lib[1];
  ((unsigned char*)(&CharNum))[3]=lib[0];
#else
  ((unsigned char*)(&CharNum))[0]=lib[0];
  ((unsigned char*)(&CharNum))[1]=lib[1];
  ((unsigned char*)(&CharNum))[2]=lib[2];
  ((unsigned char*)(&CharNum))[3]=lib[3];
#endif
  Font->CharNum=CharNum;


  lib=&lib[4];

  Font->FontHeight=lib[0];
  Font->FontMaxWidth=lib[1];
  Font->NumOfHorizontalBytes=lib[2];
  
  if(lib[3]&0x80){
    Font->IsHorizontal=0;
  }else{
    Font->IsHorizontal=-1;
  }

  if(lib[3]&0x40){
    Font->IsBigend=-1;
  }else{
    Font->IsBigend=0;
  }
  
  Font->NumOfBitForPerPix=lib[3]&0x3F;

  if((Font->NumOfBitForPerPix!=1)&&(Font->NumOfBitForPerPix!=2)&&(Font->NumOfBitForPerPix!=4)&&(Font->NumOfBitForPerPix!=8)){

    return -1;
  }

  return 0;
}




